<!DOCTYPE html>
<html>
<head>
    <title>WebRTC</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <script src="js/jquery-1.8.0.min.js"></script>
    <script src="js/adapter.js"></script>
    <style>
        #log {
            width: 100%;
            height: 200px;
            border: solid 1px;
            overflow-y: scroll;
        }

        input[type='button'] {
            width: 300px;
            height: 50px;
        }
    </style>
</head>
<body>
<video id="localVideo" autoplay></video>
<video id="remoteVideo" autoplay></video>
<div>
    <input type="button" id="start" value="Start" onclick="onClickStart()"/>
    <input type="button" id="guest" value="Guest" onclick="onClickGuest()"/>
</div>
<div id="log">
    <ul></ul>
</div>
<script type="text/javascript">
    var url = "";
    if (window.location.protocol === 'http:') {
        url = 'ws://' + window.location.host + '/websocket';
    } else {
        url = 'wss://' + window.location.host + '/websocket';
    }

    var signalingChannel = new WebSocket(url);
    var configuration = {
        /*'iceServers': [{
         //'url': 'stun:stun.l.google.com:19302'
         'url': 'stun:stun.freeswitch.org'
         }]*/
        'iceServers': [
            {"url": "stun:stun.freeswitch.org"},
            {"url": "stun:stun.xten.com"},
            {"url": "stun:stun.ekiga.net"}
        ]
    };
    var pc;
    var localVideo;
    var remoteVideo;

    function log(msg) {
        $("#log").find("ul").prepend("<li>" + new Date().Format("yyyy-MM-dd hh:mm:ss") + "=" + msg + "</li>");
    }

    function onClickStart() {
        start();
        signalingChannel.send(JSON.stringify({
            'makehost': '1'
        }));
    }
    var bGuest = false;
    function onClickGuest() {
        bGuest = true;
        signalingChannel.send(JSON.stringify({
            'makeguest': '1'
        }));
    }

    // call start() to initiate
    function start() {
        pc = new RTCPeerConnection(configuration);
        localVideo = $("#localVideo")[0];
        remoteVideo = $("#remoteVideo")[0];

        // send any ice candidates to the other peer
        pc.onicecandidate = function (evt) {
            if (evt.candidate) {
                signalingChannel.send(JSON.stringify({
                    'candidate': evt.candidate
                }));
                log("send candidate." + evt.candidate);
            }
        };

        // let the 'negotiationneeded' event trigger offer generation
        pc.onnegotiationneeded = function () {
            //if(!bGuest){
            log("creating Offer.");
            pc.createOffer(localDescCreated, logError);
            //}
        };

        // once remote stream arrives, show it in the remote video element
        pc.onaddstream = function (evt) {
            log("receiving remote video.");
            remoteVideo.src = URL.createObjectURL(evt.stream);
        };

        // get a local stream, show it in a self-view and add it to be sent
        navigator.getUserMedia({
            'audio': true,
            'video': true
        }, function (stream) {
            log("starting local video.");
            localVideo.src = URL.createObjectURL(stream);
            pc.addStream(stream);
        }, logError);
    }

    function localDescCreated(desc) {
        pc.setLocalDescription(desc, function () {
            log("got local sdp.");
            signalingChannel.send(JSON.stringify({
                'sdp': pc.localDescription
            }));
        }, logError);
    }

    signalingChannel.onclose = function (event) {
        log("WS Closed=" + event)
    };

    signalingChannel.onerror = function (event) {
        log("WS ERROR=" + event)
    };

    signalingChannel.onopen = function (event) {
        log("Connection established! " + event)
    };

    signalingChannel.onmessage = function (evt) {
        var message = null;
        try {
            message = JSON.parse(evt.data);
        } catch (err) {
            //alert("Json Parse Error By OnMessage!");
        }
        if (message === null) {
            if (evt && evt.data)
                log("response=" + evt.data);
            return;
        }

        if (!pc && (message.sdp || message.candidate))
            start();

        if (message.sdp) {
            log("getting remote sdp=");
            var remoteSDP = JSON.parse(message.sdp);
            log("getting remote sdp OBJECT=" + remoteSDP);
            pc.setRemoteDescription(new RTCSessionDescription(remoteSDP), function () {
                log("got remote sdp.");
                // if we received an offer, we need to answer
                if (pc.remoteDescription.type === 'offer') {
                    log("creating Answer.");
                    pc.createAnswer(localDescCreated, logError2);
                }
            }, logError2);
        } else if (message.candidate) {
            log("receiving candidate");
            var remoteCandidate = JSON.parse(message.candidate);
            pc.addIceCandidate(new RTCIceCandidate(remoteCandidate));
        } else {
            log("msg=" + message);
        }
    };

    function logError(error) {
        log(error.name + ': ' + error.message);
    }
    function logError2(error) {
        log(error);
    }


    // 对Date的扩展，将 Date 转化为指定格式的String
    // 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
    // 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
    // 例子：
    // (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
    // (new Date()).Format("yyyy-M-d h:m:s.S")   ==> 2006-7-2 8:9:4.18
    Date.prototype.Format =function(format){
        var o = {
            "M+" : this.getMonth()+1, //month
            "d+" : this.getDate(),    //day
            "h+" : this.getHours(),   //hour
            "m+" : this.getMinutes(), //minute
            "s+" : this.getSeconds(), //second
            "q+" : Math.floor((this.getMonth()+3)/3),  //quarter
            "S" : this.getMilliseconds() //millisecond
        };
        if(/(y+)/.test(format)) format=format.replace(RegExp.$1,(this.getFullYear()+"").substr(4- RegExp.$1.length));
        for(var k in o)
            if(new RegExp("("+ k +")").test(format))
                format = format.replace(RegExp.$1,RegExp.$1.length===1? o[k]:("00"+ o[k]).substr((""+ o[k]).length));
        return format;
    }
</script>
</body>
</html>